<?php

declare(strict_types=1);

namespace App\Server;

use Hyperf\Contract\OnReceiveInterface;
use Hyperf\Context\ApplicationContext;
use Hyperf\DbConnection\Db;
use Psr\Log\LoggerInterface;
use Hyperf\Logger\LoggerFactory;
use App\Service\GfunService;
use App\Service\MonitorService;
use Hyperf\Di\Annotation\Inject;

class TcpServer implements OnReceiveInterface
{
    private $gfunService;
    private $monitorService;

    public function __construct(LoggerFactory $loggerFactory,GfunService $gfunService,MonitorService $monitorService)
    {
        // 第一个参数对应日志的 name, 第二个参数对应 config/autoload/logger.php 内的 key
        $this->logger = $loggerFactory->get('log', 'default');
          $this->gfunService=$gfunService;
          $this->monitorService=$monitorService;
    }
    protected LoggerInterface $logger;


//     #[Inject]
//     private ?GfunService $gfunService;
//
//
//     #[Inject]
//     private ?MonitorService $monitorService;


    
    public $station_id = 10;

    public $device_unit_key = 'com:';


    public function getExecuteId($event = ''){
        return $event.'-'.getMillisecond().rand(10000,99999);
    }
    public function addLog($station_id,$macno,$execute_id,$msg_type,$data_post){
        Db::table('log')->insert([
            'station_id' => $station_id,
            'macno'=>$macno,
            'execute_id'=>$execute_id,
            'msg_type'=>$msg_type,
            'text'=>$data_post,
            'ctime'=>time(),
            'ctime_desc'=>date('Y-m-d H:i:s',time()),
        ]);
        return true;
    }


    //监听接收事件
    public function onReceive($server, int $fd, int $reactorId, string $data): void
    {

        //$this->logger->info("revc:$fd--{$data}");
        //$data = json_decode($data,true);
//        $msgType = !empty($data['msgType'])?$data['msgType']:'';
//        $deviceNum = !empty($data['deviceNum'])?$data['deviceNum']:'';
//        $executeId = !empty($data['executeId'])?$data['executeId']:'';
//        $status = isset($data['status'])&&$data['status']?1:2;
//        $dataInfo = !empty($data['dataInfo'])?$data['dataInfo']:[];
//
//        if(!$msgType) return;
//        $returnData = [
//            'executeId' => $executeId,
//            'deviceNum' => $deviceNum,
//        ];
//        $updateLogData = [
//            'revc_data'=>$dataInfo?json_encode($dataInfo,JSON_UNESCAPED_UNICODE):'',
//            'revc_time'=>time(),
//            'status'=>$status
//        ];

        //$this->bindDevice($deviceNum,$fd);

        $clientInfo = [
            'address' => 'local',
            'port' => $fd
        ];
        //$msg = date("9001---Y-m-d H:i:s",time())."----".$clientInfo['address']."|".$clientInfo['port']."|Received-origin:".$data;
        //$this->logger->info($msg);
        //echo "$msg\n";
        $str = $this->gfunService::strtohex($data);
        $msg = date("接收---Y-m-d H:i:s",time())."----".$clientInfo['address']."|".$clientInfo['port']."|".substr($str,12,2)."|Received-hex:".$str;
        $this->logger->info($msg);
        echo "$msg\n";
        //echo "Converted data: " . mb_convert_encoding($data, 'UTF-8', 'GBK') . "\n";
        // 监听到的信息解析后得到结果
        $send = $this->monitorService::parseData($this->gfunService::strtohex($data),$clientInfo,$server); // 在redisreal.php文件中解析端口接收到的信息，包含心跳信息、设备主动上传信息、下发命令应答指令等。

        if(!empty($send)){
            $command = substr($send, 12, 2);
            $msg=date("回复---Y-m-d H:i:s")."----".$clientInfo['address']."|".$clientInfo['port']."|$command|Send:".$send."\n";
            echo "$msg\n";
            $this->logger->info($msg);
            $server->send($fd,hex2bin($send));
        }


//        //日志记录
//        $addLogData = [
//            'execute_id'=>$executeId,
//            'macno'=>$deviceNum,
//        ];
//        Db::table('epidemic_log')->insert($addLogData);
    }

    public function bindDevice($deviceNum,$fd){
        //心跳刷新缓存
        $key = $this->device_unit_key.$this->station_id;
        //$redis = ApplicationContext::getContainer()->get(\Redis::class);
        $redis = redis();
        $fdList = $redis->sMembers($key);//往社区集合添加
        //如果当前客户端在客户端集合中,就刷新
        if (in_array($fd, $fdList)) {
            $redis->sAdd($key, $fd);
            $redis->expire($key, 7200);
        }
        $redis->set($deviceNum,$fd,300);
    }

    //监听链接事件
    public function onConnect($server,int $fd){
        $redis = redis();
        $key = $this->device_unit_key.$this->station_id;
        $res1 = $redis->sAdd($key, $fd);
        $res = $redis->expire($key, 7200);
        echo "$fd client : connect\n";
    }

    /**
     * 客户端失去链接
     * @param Server $server
     * @param int $fd
     * @param int $reactorId
     */
    public function onClose($server, int $fd): void
    {
        $key = $this->device_unit_key.$this->station_id;
        //删掉客户端id
        $redis = redis();
        //移除集合中指定的value
        $redis->sRem($key, $fd);
        echo "$fd client : closed\n";

    }


}